const colorDict = [
    {color: '#30fc31', label:'热带低压', ranges:[6, 7]},
    {color: '#307efa', label:'热带风暴', ranges:[8, 9]},
    {color: '#fffc00', label:'强热带风暴', ranges:[10, 11]},
    {color: '#ff9c00', label:'台风', ranges:[12, 13]},
    {color: '#fb7cff', label:'强台风', ranges:[14, 15]},
    {color: '#fa3030', label:'超强台风', ranges:[16, 20 ]}
]

class TyphoonLeaflet {
    constructor(map, code) {
        this.map = map
        this.playFlag = 0
        this.playIndex = 0
        this.layerGroup = L.layerGroup().addTo(map)

        // 预报图层
        this.layerGroupForecast = {}

        const url = `https://data.istrongcloud.com/v2/data/complex/${code}.json`
        fetch(url).then(res => res.json()).then(res => {
            this.typhoonData = res[0]
            this.addTyphoonName()
            this.play()
        })
    }

    addTyphoonName() {
        const {lng, lat} = this.typhoonData.points[0]
        const icon = L.divIcon({className: 'typhoon-name'});
        this.typhoonName = L.marker([lat, lng], {icon: icon}).addTo(this.map);
        this.typhoonName.getElement().innerText = `${this.typhoonData.tfbh}${this.typhoonData.name}`
    }

    getColor(power) {
        for (let i = 0; i < colorDict.length; i++) {
            const data = colorDict[i]
            const [min, max] = data.ranges
            if(power >= min && power <= max) {
                return data.color
            }
        }
        return '#ffffff'
    }

    play() {
        const that = this
        if(that.playIndex >= that.typhoonData.points.length){
            that.stop()
            let landInfo = {}
            if(that.typhoonData.land.length > 0) {
                landInfo = that.typhoonData.land[0]
            } else {
                const {lng, lat} = that.typhoonData.points[that.typhoonData.points.length - 1]
                // 添加登录点信息
                landInfo = {
                    land_time: "2020-10-13T19:20:00",
                    lng,
                    lat,
                    position: "海南省琼海市沿海"
                }
            }

            const latlng = [landInfo.lat, landInfo.lng]
            that.landInfo = L.popup({
                offset: [0, -5],
                autoClose: false,
                closeOnClick: false
            })
            const content = `
                <div class="field-item"><label class="field-label">登录地点：</label>${landInfo.position}</div>
                <div class="field-item"><label class="field-label">登录位置：</label>${[landInfo.lng, landInfo.lat].join(', ')}</div>
                <div class="field-item"><label class="field-label">登录时间：</label>${landInfo.land_time}</div>
            `
            that.landInfo.setLatLng(latlng)
                .setContent(content)
                .openOn(map);
            return
        }
        that.playByIndex()
        that.playIndex++
        that.playFlag = setTimeout(() => {
            that.play()
        }, 60)
    }

    playByIndex(index) {
        const that = this
        if(index) {
            that.playIndex = index
            that.stop()
        }
        that.layerGroup.clearLayers()
        // 展示风圈
        const currentData = that.typhoonData.points[that.playIndex]
        const radius7 = currentData['radius7_quad']
        const radius10 = currentData['radius10_quad']
        const radius12 = currentData['radius12_quad']
        const center = [currentData.lng, currentData.lat]
        that.addTyphoonCircle(center, radius7, '7')
        that.addTyphoonCircle(center, radius10, '10')
        that.addTyphoonCircle(center, radius12, '12')

        // 如果是播放中，展示到当前，如果是点击，则全部展示
        const endIndex = index ? that.typhoonData.points.length - 1 : that.playIndex

        // 展示路径线
        let latlngs = []
        for(let i = 0; i <= endIndex; i++) {
            const point = that.typhoonData.points[i]
            const {lng, lat} = point
            latlngs.push([lat, lng])
        }
        L.polyline(latlngs, {
            color: '#666',
            weight: 2
        }).addTo(this.layerGroup);

        // 展示路径点
        for(let i = 0; i <= endIndex; i++) {
            const point = that.typhoonData.points[i]
            const {lng, lat} = point
            const color = that.getColor(point.power)
            const circle = L.circleMarker(new L.LatLng(lat, lng), {
                color: '#666',
                weight: 1,
                opacity: 1,
                fillColor: color,
                fillOpacity: 1,
                radius: 4,
            }).addTo(that.layerGroup);
            point.index = i
            circle.data = point
            circle.on('click', function () {
                that.playByIndex(this.data.index)
            })
            circle.on('mouseover', function () {
                this.setRadius(8)
                const dict = [
                    {"name":"移向", code: "move_dir", unit: ''},
                    {"name":"移速", code: "move_speed", unit: 'm/s'},
                    {"name":"压强", code: "pressure", unit: '百帕'},
                    {"name":"七级风圈", code: "radius7", unit: '千米'},
                    {"name":"十级风圈", code: "radius10", unit: '千米'},
                    {"name":"十二级风圈", code: "radius12", unit: '千米'},
                    {"name":"移速", code: "speed", unit: 'm/s'},
                    {"name":"经过时间", code: "time", unit: ''},
                ]
                const {lat, lng} = this.data
                let content = `
                    <h4 class="field-header">${that.typhoonData.name}${that.typhoonData.tfbh}</h4>
                    <div class="field-item"><label class="field-label">中心位置：</label>${[lng, lat].join(',')}</div>
                `
                dict.forEach(d => {
                    const {code, name, unit} = d
                    let value = this.data[code]
                    value = value ? value + unit : '/'
                    content += `<div class="field-item"><label class="field-label">${name}：</label>${value}</div>`
                })
                const latlng = [lat, lng]
                that.popup = L.popup({
                    offset: [0, -5]
                })
                that.popup.setLatLng(latlng)
                    .setContent(content)
                    .openOn(map);
            })
            circle.on('mouseout', function () {
                this.setRadius(4)
                that.popup.remove()
            })
            // 最后一个点
            if(i === that.playIndex) {
                if(that.typhoonIcon) that.typhoonIcon.remove()
                const icon = L.divIcon({className: 'typhoon-icon'});
                that.typhoonIcon = L.marker([lat, lng], {icon: icon}).addTo(that.map);
                const svg = `<svg class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1717" width="32" height="32"><path d="M748.8 128c105.6 0 201.6 41.6 275.2 102.4-96-128-246.4-214.4-419.2-214.4-140.8 0-268.8 57.6-364.8 150.4-96 80-160 204.8-160 345.6 0 163.2 86.4 304 214.4 384l-12.8 3.2c-108.8 0-204.8-38.4-281.6-102.4 96 128 246.4 214.4 419.2 214.4 108.8 0 208-32 291.2-89.6 153.6-70.4 259.2-227.2 259.2-406.4 0-166.4-89.6-310.4-220.8-387.2z m-224 169.6c118.4 0 211.2 96 211.2 214.4s-96 214.4-211.2 214.4-211.2-96-211.2-214.4 92.8-214.4 211.2-214.4z" p-id="1718" fill="${color}"></path></svg>`
                const div = document.createElement('div')
                div.classList.add('icon')
                div.innerHTML = svg
                that.typhoonIcon.getElement().appendChild(div)
            }
        }

        // 添加预报路径
        const setsColor = {
            '中国': '#f5000e',
            '中国香港': '#6533b5',
            '中国台湾': '#1f46b0',
            '韩国': '#41c1f6',
            '菲律宾': '#000',
            '美国': '#3187d6',
            '日本': '#f600ad',
        }
        const forecast = currentData.forecast || []
        // 删除预报数据
        for(let sets in that.layerGroupForecast) {
            that.layerGroupForecast[sets].remove()
        }
        that.layerGroupForecast = {}

        forecast.forEach(fd => {
            const {sets, points} = fd
            let coords = [[center[1], center[0]]]
            points.forEach(pd => {
                const {lng, lat} = pd
                coords.push([lat, lng])
            })

            if(!that.layerGroupForecast[sets]) {
                that.layerGroupForecast[sets] = L.layerGroup().addTo(map)
            }
            // 添加预报线
            L.polyline(coords, {
                color: setsColor[sets],
                weight: 2,
                dashArray: [5, 5]
            }).addTo(that.layerGroupForecast[sets]);
            // 添加预报点
            points.forEach(pd => {
                const {lng, lat} = pd
                const color = that.getColor(pd.power)
                const circle = L.circleMarker(new L.LatLng(lat, lng), {
                    color: '#666',
                    weight: 1,
                    opacity: 1,
                    fillColor: color,
                    fillOpacity: 1,
                    radius: 4,
                }).addTo(that.layerGroupForecast[sets]);
                circle.data = pd
                circle.on('mouseover', function () {
                    this.setRadius(8)
                    const dict = [
                        {"name":"压强", code: "pressure", unit: '百帕'},
                        {"name":"移速", code: "speed", unit: 'm/s'}
                    ]
                    const {lat, lng} = this.data
                    let content = `
                    <h4 class="field-header">${that.typhoonData.name}${that.typhoonData.tfbh}</h4>
                    <div class="field-item"><label class="field-label">中心位置：</label>${[lng, lat].join(',')}</div>
                `
                    dict.forEach(d => {
                        const {code, name, unit} = d
                        let value = this.data[code]
                        value = value ? value + unit : '/'
                        content += `<div class="field-item"><label class="field-label">${name}：</label>${value}</div>`
                    })
                    const latlng = [lat, lng]
                    that.popup = L.popup({
                        offset: [0, -5]
                    })
                    that.popup.setLatLng(latlng)
                        .setContent(content)
                        .openOn(map);
                })
                circle.on('mouseout', function () {
                    this.setRadius(4)
                    that.popup.remove()
                })
            })
        })
    }

    addTyphoonCircle(center, radiusData, type) {
        if(!radiusData.ne) return
        center = proj4(proj4('EPSG:4326'), proj4('EPSG:3857'), center);
        let latlngs = [];
        let _angInterval = 6;
        let _pointNums = 360 / (_angInterval * 4);
        let quadrant = {
            // 逆时针算角度
            '0': 'ne',
            '1': 'nw',
            '2': 'sw',
            '3': 'se'
        };
        for (let i = 0; i < 4; i++) {
            let _r = parseFloat(radiusData[quadrant[i]]) * 1000; // 单位是km
            if (!_r) _r = 0;
            for (let j = i * _pointNums; j <= (i + 1) * _pointNums; j++) {
                let _ang = _angInterval * j;
                let x = center[0] + _r * Math.cos((_ang * Math.PI) / 180);
                let y = center[1] + _r * Math.sin((_ang * Math.PI) / 180);
                const coord = proj4(proj4('EPSG:3857'), proj4('EPSG:4326'), [x, y]);
                latlngs.push(coord.reverse());
            }
        }
        const colorDict = {
            '7': '#00bab2',
            '10': '#ffff00',
            '12': '#da7341'
        }
        L.polygon(latlngs, {
            color: colorDict[type],
            weight: 1,
            opacity: 1,
            fillColor: colorDict[type],
            fillOpacity: 0.3,
        }).addTo(this.layerGroup);
    }

    stop() {
        window.clearTimeout(this.playFlag)
    }

    remove() {
        this.typhoonName.remove()
        this.landInfo.remove()
        this.typhoonIcon.remove()
        this.layerGroup.remove()
        for(let sets in this.layerGroupForecast) {
            this.layerGroupForecast[sets].remove()
        }
        window.clearTimeout(this.playFlag)
    }

    setForecastVisible(visible, sets) {
        if(this.layerGroupForecast[sets]) {
            visible ? this.layerGroupForecast[sets].remove() : this.layerGroupForecast[sets].addTo(this.map)
        }
    }
}

class TyphoonPlayer {
    constructor(map) {
        this.map = map
        this.typhoons = {}
        this.addWarnLines()
    }

    addWarnLines() {
        const line24 = [
            [
                0,
                105
            ],
            [
                4.5,
                113
            ],
            [
                11,
                119
            ],
            [
                18,
                119
            ],
            [
                22,
                127
            ],
            [
                34,
                127
            ]
        ]
        const line48 = [
            [
                0,
                105
            ],
            [
                0,
                120
            ],
            [
                15,
                132
            ],
            [
                34,
                132
            ]
        ]
        L.polyline(line48, {
            color: '#0ecd0e',
            weight: 2,
            dashArray: [8, 8]
        }).addTo(this.map);

        L.polyline(line24, {
            color: '#00f',
            weight: 2
        }).addTo(this.map);
    }

    playTyphoon(code = '202016') {
       this.typhoons[code] = new TyphoonLeaflet(this.map, code)
    }

    stopTyphoon(code = '202016') {
        const typhoon = this.typhoons[code]
        if(typhoon) typhoon.stop()
    }

    removeTyphoon(code = '202016') {
        const typhoon = this.typhoons[code]
        if(typhoon) {
            typhoon.remove()
            delete this.typhoons[code]
        }
    }

    setForecastVisible(visible, sets) {
        for(let tfbh in this.typhoons) {
            this.typhoons[tfbh].setForecastVisible(visible, sets)
        }
    }
}